package com.gzhryc.shared_device.oem.code.place.services;

import com.gzhryc.common.StringTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.shared_device.bxscn.code.dao.db.BXSCNFeeTemplate;
import com.gzhryc.shared_device.bxscn.code.dao.db.BXSCNShopFeeTemplate;
import com.gzhryc.shared_device.bxscn.code.services.BXSCNFeeTemplateService;
import com.gzhryc.shared_device.bxscn.code.services.BXSCNShopFeeTemplateService;
import com.gzhryc.shared_device.bxscn.code.services.PortableEnergyBatteryService;
import com.gzhryc.shared_device.bxscn.code.services.PortableEnergyCabinetService;
import com.gzhryc.shared_device.bxscn.code.services.dto.PortableEnergyBatterySearch;
import com.gzhryc.shared_device.bxscn.code.services.dto.PortableEnergyCabinetSearch;
import com.gzhryc.shared_device.cdb.code.dao.db.CDBFeeTemplate;
import com.gzhryc.shared_device.cdb.code.services.BatteryCabinetService;
import com.gzhryc.shared_device.cdb.code.services.CDBFeeTemplateService;
import com.gzhryc.shared_device.cdb.code.services.dto.BatteryCabinetSearch;
import com.gzhryc.shared_device.cdcz.code.CDCZCostConfig;
import com.gzhryc.shared_device.cdcz.code.dao.db.CDCZFeeTemplate;
import com.gzhryc.shared_device.cdcz.code.dao.models.CDCZPowerIntervalMoneyContent;
import com.gzhryc.shared_device.cdcz.code.services.CDCZFeeTemplateService;
import com.gzhryc.shared_device.cdcz.code.services.ChargeSocketService;
import com.gzhryc.shared_device.cdcz.code.services.dto.ChargeSocketSearch;
import com.gzhryc.shared_device.oem.code.ConfigUtils;
import com.gzhryc.shared_device.oem.code.business.EBusinessType;
import com.gzhryc.shared_device.oem.code.device.EDeviceFunCode;
import com.gzhryc.shared_device.oem.code.place.dao.PlaceBusinessConfigDao;
import com.gzhryc.shared_device.oem.code.place.dao.db.PlaceBusinessConfig;
import com.gzhryc.shared_device.pcl.PCLSetMealCostContent;
import com.gzhryc.shared_device.pcl.code.dao.db.PCLFeeTemplate;
import com.gzhryc.shared_device.pcl.code.services.PCLFeeTemplateService;

import java.sql.SQLException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class PlaceBusinessConfigService {

    static Logger log = Logger.getLogger(PlaceBusinessConfigService.class);

    public static PlaceBusinessConfigService self() {
        return MultiDBTools.getService(PlaceBusinessConfigService.class, true);
    }

    public static PlaceBusinessConfigService self(String jdbcKey) {
        return MultiDBTools.getService(jdbcKey, PlaceBusinessConfigService.class, true);
    }

    PlaceBusinessConfigDao dao;

    public PlaceBusinessConfigService(String jdbcKey) {
        this.dao = new PlaceBusinessConfigDao(jdbcKey);
    }

    public List<PlaceBusinessConfig> findByPlaceId(Long placeId){
        if(placeId != null) {
            Conditions conditions = new Conditions(PlaceBusinessConfig.class);
            conditions.and().is("placeId",placeId);
            try {
                return dao.findByCondition(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public List<PlaceBusinessConfig> findByBusinessTypeAndPlaceIds(String businessType, List<Long> placeIds){
        if(StringTools.isNotBlank(businessType) && placeIds != null && placeIds.size() > 0) {
            Conditions conditions = new Conditions(PlaceBusinessConfig.class);
            conditions.and().is("businessType",businessType);
            conditions.and().in("placeId",placeIds);

            try {
                return dao.findByCondition(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public Long countConfiguredByPlaceId(Long placeId){
        if(placeId != null) {
            Conditions conditions = new Conditions(PlaceBusinessConfig.class);
            conditions.and().is("placeId",placeId);
            conditions.and().isNotNull("feeTemplateId");

            try {
                return dao.count(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return 0L;
    }

    public Long countByFeeTemplateId(String businessType,Long feeTemplateId){
        if(StringTools.isNotBlank(businessType) && feeTemplateId != null){
            Conditions conditions = new Conditions(PlaceBusinessConfig.class);
            conditions.and().is("businessType",businessType);
            conditions.and().is("feeTemplateId",feeTemplateId);

            try {
                return dao.count(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return 0L;
    }

    public PlaceBusinessConfig getByKeys(Long placeId, String businessType){
        if(placeId != null && StringTools.isNotBlank(businessType)){
            Conditions conditions = new Conditions(PlaceBusinessConfig.class);
            conditions.and().is("placeId",placeId);
            conditions.and().is("businessType",businessType);

            try {
                return dao.get(conditions);
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return null;
    }

    public Long getCDCZPayMoney(Long placeId, Double maxUsePower){
        //结算金额
        CDCZPowerIntervalMoneyContent pimContent = null;
        Long payMoney = null;
        CDCZFeeTemplate feeTemplate = null;
        PlaceBusinessConfig deviceFunc = PlaceBusinessConfigService.self().getByKeys(placeId,EDeviceFunCode.CDCZ.index());
        if(deviceFunc != null && deviceFunc.getFeeTemplateId() != null) {
            feeTemplate = CDCZFeeTemplateService.self().getById(deviceFunc.getFeeTemplateId());
        }
        if (feeTemplate != null && StringTools.isNotBlank(feeTemplate.getPimContent())) {
            pimContent = JsonTools.fromJson(feeTemplate.getPimContent(), CDCZPowerIntervalMoneyContent.class);
        } else {
            CDCZCostConfig costConfig = ConfigUtils.getCDCZCostConfig();
            if (StringTools.isNotBlank(costConfig.getPimContent())) {
                pimContent = JsonTools.fromJson(costConfig.getPimContent(), CDCZPowerIntervalMoneyContent.class);
            }
        }
        if (pimContent != null && pimContent.getItems() != null && pimContent.getItems().size() > 0) {
            for (CDCZPowerIntervalMoneyContent.Item item : pimContent.getItems()) {
                if (item.getMinPower() <= maxUsePower && item.getMaxPower() > maxUsePower) {
                    payMoney = item.getMoney();
                }
            }
            if (payMoney == null) {
                log.error("未找到功率区间收费标准，使用最高收费，网点ID：{{0}}，最大使用功率：{{1}}", placeId, maxUsePower);
                CDCZPowerIntervalMoneyContent.Item item = pimContent.getItems().get((pimContent.getItems().size() - 1));
                payMoney = item.getMoney();
            }
        }
        return payMoney;
    }

    public boolean updatePCLCostTemplate(Long placeId,Long feeTemplateId) throws LogicException {
        PlaceBusinessConfig businessConfig = PlaceBusinessConfigService.self().getByKeys(placeId, EBusinessType.PCL.index());
        if(businessConfig == null) {
            throw new LogicException("未找到网点该业务类型");
        }
        PCLFeeTemplate feeTemplate = PCLFeeTemplateService.self().getById(feeTemplateId);
        if(feeTemplate == null) {
            throw new LogicException("未找到收费模版");
        }

        PCLSetMealCostContent costContent = new PCLSetMealCostContent();
        if(StringTools.isNotBlank(businessConfig.getCostContent())){
            costContent = JsonTools.fromJson(businessConfig.getCostContent(), PCLSetMealCostContent.class);
        }

        boolean flag = true;
        for(PCLSetMealCostContent.Item item : costContent.getItems()){
            if(item.getDeviceTypeId().equals(feeTemplate.getDeviceTypeId())){
                item.setFeeTemplateId(feeTemplate.getId());
                flag = false;
                break;
            }
        }

        if(flag){
            PCLSetMealCostContent.Item item = new PCLSetMealCostContent.Item();
            item.setDeviceTypeId(feeTemplate.getDeviceTypeId());
            item.setFeeTemplateId(feeTemplate.getId());
            costContent.getItems().add(item);
        }

        Conditions conditions = new Conditions(PlaceBusinessConfig.class);
        conditions.and().is("placeId",placeId);
        conditions.and().is("businessType",EBusinessType.PCL.index());


        PlaceBusinessConfig updateEntity = new PlaceBusinessConfig();
        updateEntity.setCostContent(JsonTools.toJson(costContent));

        try {
            return dao.updateNotNull(updateEntity,conditions) > 0;
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return false;
    }

    public boolean add(PlaceBusinessConfig businessConfig)  throws LogicException{
        PlaceBusinessConfig temp = getByKeys(businessConfig.getPlaceId(),businessConfig.getBusinessType());
        if(temp != null){
            throw new LogicException(businessConfig.getBusinessTypeName() + "业务已存在");
        }
        businessConfig.setCreateDate(new Date());
        try {
            return dao.insert(businessConfig) > 0;
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
        }
        return false;
    }

    public boolean setFeeTemplateId(Long placeId,String businessType,Long feeTemplateId) throws LogicException {
        if(placeId != null && StringTools.isNotBlank(businessType)){
            PlaceBusinessConfig businessConfig = getByKeys(placeId,businessType);

            Conditions conditions = new Conditions(PlaceBusinessConfig.class);
            conditions.and().is("placeId",placeId);
            conditions.and().is("businessType",businessType);

            if(feeTemplateId != null && feeTemplateId > 0) {
                PlaceBusinessConfig updateEntity = new PlaceBusinessConfig();
                if (EBusinessType.CDB.index().equals(businessType)) {
                    CDBFeeTemplate feeTemplate = CDBFeeTemplateService.self().getById(feeTemplateId);
                    if (feeTemplate == null) {
                        throw new LogicException("未找到共享充电宝收费模版");
                    }
                    updateEntity.setFeeTemplateId(feeTemplate.getId());
                    updateEntity.setFeeTemplateTitle(feeTemplate.getTitle());
                } else if (EBusinessType.CDCZ.index().equals(businessType)) {
                    CDCZFeeTemplate feeTemplate = CDCZFeeTemplateService.self().getById(feeTemplateId);
                    if (feeTemplate == null) {
                        throw new LogicException("未找到充电插座收费模版");
                    }
                    updateEntity.setFeeTemplateId(feeTemplate.getId());
                    updateEntity.setFeeTemplateTitle(feeTemplate.getTitle());
                }else if (EBusinessType.BXSCN.index().equals(businessType)) {
                    BXSCNFeeTemplate feeTemplate = BXSCNFeeTemplateService.self().getById(feeTemplateId);
                    if (feeTemplate == null) {
                        throw new LogicException("未找到便携式电池收费模版");
                    }
                    updateEntity.setFeeTemplateId(feeTemplate.getId());
                    updateEntity.setFeeTemplateTitle(feeTemplate.getTitle());
                }else if (EBusinessType.BXSCN_SHOP.index().equals(businessType)) {
                    BXSCNShopFeeTemplate feeTemplate = BXSCNShopFeeTemplateService.self().getById(feeTemplateId);
                    if (feeTemplate == null) {
                        throw new LogicException("未找到便携式电池(门店)收费模版");
                    }
                    updateEntity.setFeeTemplateId(feeTemplate.getId());
                    updateEntity.setFeeTemplateTitle(feeTemplate.getTitle());
                }else if (EBusinessType.PCL.index().equals(businessType)) {
                    PCLFeeTemplate feeTemplate = PCLFeeTemplateService.self().getById(feeTemplateId);
                    if (feeTemplate == null) {
                        throw new LogicException("未找到便捷线充收费模版");
                    }

                    PCLSetMealCostContent costContent = null;
                    boolean flag = true;
                    if(businessConfig != null && StringTools.isNotBlank(businessConfig.getCostContent())){
                        costContent = JsonTools.fromJson(businessConfig.getCostContent(), PCLSetMealCostContent.class);
                        if (costContent != null && costContent.getItems() != null && costContent.getItems().size() > 0) {
                            for(PCLSetMealCostContent.Item item : costContent.getItems()){
                                if(item.getDeviceTypeId().equals(feeTemplate.getDeviceTypeId())){
                                    item.setFeeTemplateId(feeTemplate.getId());
                                    flag = false;
                                    break;
                                }
                            }
                        }
                    }

                    if(costContent == null){
                        costContent = new PCLSetMealCostContent();
                    }

                    if(flag){
                        PCLSetMealCostContent.Item item = new PCLSetMealCostContent.Item();
                        item.setDeviceTypeId(feeTemplate.getDeviceTypeId());
                        item.setFeeTemplateId(feeTemplate.getId());
                        costContent.getItems().add(item);
                    }
                    updateEntity.setCostContent(JsonTools.toJson(costContent));
                }else {
                    throw new LogicException("暂不支持的设备功能");
                }


                if(businessConfig == null){
                    updateEntity.setPlaceId(placeId);
                    updateEntity.setBusinessType(businessType);

                    try {
                        return dao.insert(updateEntity) > 0;
                    } catch (SQLException e) {
                        log.error(e.getMessage(), e);
                    }
                }else {
                    try {
                        return dao.updateNotNull(updateEntity, conditions) > 0;
                    } catch (SQLException e) {
                        log.error(e.getMessage(), e);
                    }
                }
            }else {
                if(businessConfig == null){
                    return true;
                }
                Map<String,Object> map = new HashMap<>();
                map.put("feeTemplateId",null);
                map.put("feeTemplateTitle",null);

                try {
                    return dao.update(map, conditions) > 0;
                } catch (SQLException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
        return false;
    }

    public boolean deploy(Long placeId,String businessType,Integer deviceCount) throws LogicException {
        if(placeId != null && StringTools.isNotBlank(businessType) && deviceCount != null) {
            PlaceBusinessConfig businessConfig = getByKeys(placeId,businessType);
            if(businessConfig == null){
                businessConfig = new PlaceBusinessConfig();
                businessConfig.setPlaceId(placeId);
                businessConfig.setBusinessType(businessType);
                businessConfig.setDeviceCount(deviceCount);
                businessConfig.setCreateDate(new Date());
                try {
                    return dao.insert(businessConfig) > 0;
                } catch (SQLException e) {
                    log.error(e.getMessage(), e);
                }
            }else {
                Conditions conditions = new Conditions(PlaceBusinessConfig.class);
                conditions.and().is("placeId", placeId);
                conditions.and().is("businessType", businessType);

                PlaceBusinessConfig updateEntity = new PlaceBusinessConfig();
                updateEntity.setDeviceCount(deviceCount);

                try {
                    if(dao.updateNotNullAndInc(updateEntity, conditions,"deviceCount") > 0) {
                        return true;
                    }else {
                        throw new LogicException("修改网点设备功能项中的设备数量失败");
                    }
                } catch (SQLException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
        return false;
    }

    public boolean undeploy(Long placeId,String businessType,Integer deviceCount) throws LogicException {
        if(placeId != null && StringTools.isNotBlank(businessType) && deviceCount != null) {
            PlaceBusinessConfig placeDeviceFunc = getByKeys(placeId,businessType);
            if(placeDeviceFunc == null){
                return true;
            }
            if(placeDeviceFunc.getDeviceCount() > 1) {
                Conditions conditions = new Conditions(PlaceBusinessConfig.class);
                conditions.and().is("placeId", placeId);
                conditions.and().is("businessType", businessType);

                PlaceBusinessConfig updateEntity = new PlaceBusinessConfig();
                updateEntity.setDeviceCount(deviceCount);
                try {
                    if (dao.updateNotNullAndReduce(updateEntity, conditions, "deviceCount") > 0) {
                        return true;
                    } else {
                        throw new LogicException("修改网点设备功能项中的设备数量失败");
                    }
                } catch (SQLException e) {
                    log.error(e.getMessage(), e);
                }
            }else{
                Conditions conditions = new Conditions(PlaceBusinessConfig.class);
                conditions.and().is("placeId", placeId);
                conditions.and().is("businessType", businessType);

                try {
                    return dao.deleteByCondition(conditions) > 0;
                } catch (SQLException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
        return false;
    }

    public int refreshDeviceCount(Long placeId,String businessType) {
        Long deviceCount = null;
        if (EBusinessType.CDCZ.index().equals(businessType)) {
            ChargeSocketSearch search = new ChargeSocketSearch();
            search.setPlaceId(placeId);
            deviceCount = ChargeSocketService.self().countJoinBySearch(search);
        }else if(EBusinessType.CDB.index().equals(businessType)){
            BatteryCabinetSearch search = new BatteryCabinetSearch();
            search.setPlaceId(placeId);
            deviceCount = BatteryCabinetService.self().countJoinBySearch(search);
        }else if(EBusinessType.BXSCN.index().equals(businessType)){
            PortableEnergyCabinetSearch search = new PortableEnergyCabinetSearch();
            search.setPlaceId(placeId);
            deviceCount = PortableEnergyCabinetService.self().countJoinBySearch(search);
        }else if(EBusinessType.BXSCN_SHOP.index().equals(businessType)){
            PortableEnergyBatterySearch search = new PortableEnergyBatterySearch();
            search.setPlaceId(placeId);
            deviceCount = PortableEnergyBatteryService.self().countJoinBySearch(search);
        }

        if(deviceCount != null && deviceCount > 0) {
            Conditions conditions = new Conditions(PlaceBusinessConfig.class);
            conditions.and().is("placeId", placeId);
            conditions.and().is("businessType", businessType);

            PlaceBusinessConfig updateEntity = new PlaceBusinessConfig();
            updateEntity.setDeviceCount(deviceCount.intValue());

            try {
                if (dao.updateNotNull(updateEntity, conditions) >= 0) {
                    return updateEntity.getDeviceCount();
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }else{
            Conditions conditions = new Conditions(PlaceBusinessConfig.class);
            conditions.and().is("placeId", placeId);
            conditions.and().is("businessType", businessType);

            try {
                if (dao.deleteByCondition(conditions) >= 0) {
                    return 0;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return -1;
    }

    public boolean deleteByKeys(Long placeId,String businessType) throws LogicException {
        if (placeId != null && StringTools.isNotBlank(businessType)) {
            PlaceBusinessConfig deviceFunc = getByKeys(placeId, businessType);
            if (deviceFunc != null) {
                if (deviceFunc.getDeviceCount() == 0) {
                    Conditions conditions = new Conditions(PlaceBusinessConfig.class);
                    conditions.and().is("placeId", placeId);
                    conditions.and().is("businessType", businessType);

                    try {
                        return dao.deleteByCondition(conditions) > 0;
                    } catch (SQLException e) {
                        log.error(e.getMessage(), e);
                    }
                } else {
                    throw new LogicException("已部署设备，不允许删除");
                }
            }
        }
        return false;
    }

    public boolean deleteByPlaceId(Long placeId){
        if (placeId != null) {
            Conditions conditions = new Conditions(PlaceBusinessConfig.class);
            conditions.and().is("placeId", placeId);

            try {
                return dao.deleteByCondition(conditions) >= 0;
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return false;
    }

    /**
     * 强制删除，用于移除部署设备时，移除部署设备方法已经判断了是否还有设备
     * @param placeId
     * @param businessType
     * @return
     */
    public boolean faceDeleteByKeys(Long placeId,String businessType){
        if (placeId != null && StringTools.isNotBlank(businessType)) {
            Conditions conditions = new Conditions(PlaceBusinessConfig.class);
            conditions.and().is("placeId", placeId);
            conditions.and().is("businessType", businessType);

            try {
                return dao.deleteByCondition(conditions) >= 0;
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return false;
    }
}
